package com.maojianjie.aimee.webautotest;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import javax.imageio.ImageIO;

import org.apache.commons.io.FileUtils;
import org.openqa.selenium.Dimension;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.NoAlertPresentException;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.Point;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.support.ui.WebDriverWait;

import com.maojianjie.aimee.webautotest.Locator.Type;

/**
 * 浏览器类
 * 
 * @author 毛建杰
 */
public abstract class Browser implements AutoCloseable
{
	protected WebDriver webDriver;
	protected WebDriverWait webDriverWait;

	protected abstract WebDriver createWebDriver();

	/**
	 * 设置超时时间
	 * 
	 * @param time
	 *             超时时间，单位：秒
	 */
	public void setTimeout(long time)
	{
		webDriver.manage().timeouts().pageLoadTimeout(time, TimeUnit.SECONDS);
		webDriver.manage().timeouts().setScriptTimeout(time, TimeUnit.SECONDS);
		webDriverWait = new WebDriverWait(webDriver, time);
	}

	/**
	 * 打开url
	 * 
	 * @param url
	 *            url
	 */
	public void open(String url)
	{
		if (webDriver == null)
		{
			webDriver = createWebDriver();
			setTimeout(120);
		}
		webDriver.get(url);
	}

	@Override
	/**
	 * 关闭浏览器
	 */
	public void close()
	{
		webDriver.quit();
	}

	/**
	 * 查找一个元素
	 * 
	 * @param type
	 *              元素类型
	 * @param value
	 *              元素值
	 * @return 元素
	 */
	public Element findElement(Type type, String value)
	{
		return Element.element(this, type, value);
	}

	/**
	 * 查找一组元素
	 * 
	 * @param type
	 *              元素类型
	 * @param value
	 *              元素值
	 * @return 元素数组
	 */
	public ArrayList<Element> findElements(Type type, String value)
	{
		return Element.elements(this, type, value);
	}

	/**
	 * 确认警告弹窗
	 * 
	 * @throws InterruptedException
	 *                              异常
	 */
	public void acceptAlert() throws InterruptedException
	{
		for (int i = 10; i > 0; i--)
		{
			try
			{
				Thread.sleep(500);
				webDriver.switchTo().alert().accept();
				return;
			}
			catch (NoAlertPresentException e)
			{
				if (i == 1)
				{
					throw e;
				}
			}
		}
	}

	/**
	 * 取消警告弹窗
	 * 
	 * @throws InterruptedException
	 *                              异常
	 */
	public void dismissAlert() throws InterruptedException
	{
		for (int i = 10; i > 0; i--)
		{
			try
			{
				Thread.sleep(500);
				webDriver.switchTo().alert().dismiss();
				return;
			}
			catch (NoAlertPresentException e)
			{
				if (i == 1)
				{
					throw e;
				}
			}
		}
	}

	/**
	 * 获取警告弹窗文字
	 * 
	 * @return 警告弹窗文字
	 * @throws InterruptedException
	 *                              异常
	 */
	public String getAlertText() throws InterruptedException
	{
		for (int i = 10; i > 0; i--)
		{
			try
			{
				Thread.sleep(500);
				return webDriver.switchTo().alert().getText();
			}
			catch (NoAlertPresentException e)
			{
				if (i == 1)
				{
					throw e;
				}
			}
		}
		return null;
	}

	/**
	 * 浏览器后退
	 */
	public void back()
	{
		webDriver.navigate().back();
	}

	/**
	 * 执行JavaScript
	 * 
	 * @param javaScript
	 *                   javaScript
	 */
	public void executeJavaScript(String javaScript)
	{
		((JavascriptExecutor) webDriver).executeScript(javaScript);
	}

	/**
	 * 浏览器前进
	 */
	public void forward()
	{
		webDriver.navigate().forward();
	}

	/**
	 * 获取标题
	 * 
	 * @return 标题
	 */
	public String getTitle()
	{
		return webDriver.getTitle();
	}

	/**
	 * 获取url
	 * 
	 * @return url
	 */
	public String getUrl()
	{
		return webDriver.getCurrentUrl();
	}

	/**
	 * 浏览器刷新
	 */
	public void refresh()
	{
		webDriver.navigate().refresh();
	}

	/**
	 * 滑动滚动条
	 * 
	 * @param y
	 *          滑动距离
	 */
	public void scroll(int y)
	{
		executeJavaScript("window.scrollTo(0," + y + ");");
	}

	/**
	 * 向下滑动滚动条一个页面高度
	 */
	public void scrollDown()
	{
		executeJavaScript("window.scrollTo(0,document.body.scrollHeight);");
	}

	/**
	 * 向上滑动滚动条一个页面高度
	 */
	public void scrollUp()
	{
		executeJavaScript("window.scrollTo(0,-document.body.scrollHeight);");
	}

	/**
	 * 窗口最大化
	 */
	public void setWindowMaximize()
	{
		webDriver.manage().window().maximize();
	}

	/**
	 * 设置窗口尺寸
	 * 
	 * @param width
	 *               宽度
	 * @param height
	 *               高度
	 */
	public void setWindowSize(int width, int height)
	{
		webDriver.manage().window().setSize(new Dimension(width, height));
	}

	/**
	 * 切出frame
	 */
	public void switchToDefaultContent()
	{
		webDriver.switchTo().defaultContent();
	}

	/**
	 * 切入frame
	 * 
	 * @param frame
	 *              frame
	 */
	public void switchToFrame(Element frame)
	{
		webDriver.switchTo().frame(frame.webElement);
	}

	/**
	 * 元素截图
	 * 
	 * @param element
	 *                元素
	 * @param file
	 *                保存图片路径
	 * @throws IOException
	 *                     异常
	 */
	public void screenshot(Element element, String file) throws IOException
	{
		File screenshot = ((TakesScreenshot) webDriver).getScreenshotAs(OutputType.FILE);
		if (element != null)
		{
			BufferedImage image = ImageIO.read(screenshot);
			Point point = element.webElement.getLocation();
			int width = element.webElement.getSize().getWidth();
			int height = element.webElement.getSize().getHeight();
			image = image.getSubimage(point.getX(), point.getY(), width, height);
			ImageIO.write(image, "png", screenshot);
		}
		FileUtils.copyFile(screenshot, new File(file));
	}

	/**
	 * 页面截图
	 * 
	 * @param file
	 *             保存图片路径
	 * @throws IOException
	 *                     异常
	 */
	public void screenshot(String file) throws IOException
	{
		screenshot(null, file);
	}

	/**
	 * 获取cooikes
	 * 
	 * @return cooike数组
	 */
	public ArrayList<Cooike> getCooikes()
	{
		ArrayList<Cooike> cooikes = new ArrayList<Cooike>();
		Set<org.openqa.selenium.Cookie> cookieSet = webDriver.manage().getCookies();
		Iterator<org.openqa.selenium.Cookie> it = cookieSet.iterator();
		while (it.hasNext())
		{
			org.openqa.selenium.Cookie cookie = it.next();
			cooikes.add(new Cooike(cookie.getName(), cookie.getValue()));
		}
		return cooikes;
	}

	/**
	 * 添加cooike
	 * 
	 * @param cooike
	 *               cooike
	 */
	public void addCooike(Cooike cooike)
	{
		webDriver.manage().addCookie(new org.openqa.selenium.Cookie(cooike.getName(), cooike.getValue()));
	}
}
